﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace AsteroidWar
{
    class EnemyManager
    {
        public int totalEnemyWay = 0;
        private Texture2D texture;
        private Rectangle initialFrame;
        private int frameCount;

        public List<Enemy> enemies = new List<Enemy>();
        public ShotManager enemyShotManager;
        private PlayerManager playerManager;
        private SecondPlayer secondPlayer;
        private float spawnEnemyTime = 0.0f;
        private float spawnEnemyDelayTime = 0.7f;
        private float nextWaveTime = 0.0f;
        private float nextWaveDelayTime = 9.0f;
        public int MinShip = 5;
        public int MaxShip = 7;
        private float shipShotChance = 0.2f;

        private List<List<Vector2>> pathWayPoints = new List<List<Vector2>>();
        private Dictionary<int, int> waveSpawns = new Dictionary<int, int>();

        public bool Active = true;
        public bool BossShowTime = false;
        public Boss boss;
        private float bossMove = 0.0f;
        private float bossMoveDelay = 4.0f;
        private float bossShotTime = 0.0f;
        private float bossShotTimeDelay = 2.0f;
        private Random rand = new Random();

        private void setUpWaypoints()
        {
            List<Vector2> path0 = new List<Vector2>();
            path0.Add(new Vector2(900, 300));
            path0.Add(new Vector2(-100, 300));
            pathWayPoints.Add(path0);
            waveSpawns[0] = 0;

            List<Vector2> path1 = new List<Vector2>();
            path1.Add(new Vector2(-100, 300));
            path1.Add(new Vector2(900, 300));
            pathWayPoints.Add(path1);
            waveSpawns[1] = 0;

            List<Vector2> path2 = new List<Vector2>();
            path2.Add(new Vector2(-100, 50));
            path2.Add(new Vector2(150, 50));
            path2.Add(new Vector2(200, 75));
            path2.Add(new Vector2(200, 125));
            path2.Add(new Vector2(150, 150));
            path2.Add(new Vector2(150, 175));
            path2.Add(new Vector2(200, 200));
            path2.Add(new Vector2(600, 200));
            path2.Add(new Vector2(900, 600));
            pathWayPoints.Add(path2);
            waveSpawns[2] = 0;

            List<Vector2> path3 = new List<Vector2>();
            path3.Add(new Vector2(600, -100));
            path3.Add(new Vector2(600, 250));
            path3.Add(new Vector2(580, 275));
            path3.Add(new Vector2(500, 250));
            path3.Add(new Vector2(500, 200));
            path3.Add(new Vector2(450, 175));
            path3.Add(new Vector2(400, 150));
            path3.Add(new Vector2(-100, 150));
            pathWayPoints.Add(path3);
            waveSpawns[3] = 0;

            //BOSS PATH          
            List<Vector2> path4 = new List<Vector2>();
            path4.Add(new Vector2(100, 50));
            path4.Add(new Vector2(500, 50));
            pathWayPoints.Add(path4);     
        }
        public void resetBoss()
        {
            BossShowTime = false;
            boss.sprite.Location= new Vector2(-500,-500);
            
        }

        public EnemyManager(
            Texture2D enemyTexture,
            Rectangle initialFrame,
            Texture2D shotTexture,
            Rectangle ammoFrame,
            int frameCount,
            PlayerManager playerManager,
            SecondPlayer secondPlayer,
            Rectangle screenBound,        
            Texture2D bossTexture,
            Rectangle bossFrame)
        {
            this.texture = enemyTexture;
            this.initialFrame = initialFrame;
            this.frameCount = frameCount;
            this.playerManager = playerManager;

            enemyShotManager = new ShotManager(shotTexture, ammoFrame, 1, 13, 250f, screenBound);
            boss = new Boss(bossTexture, bossFrame,4, new Vector2(300,-300) , screenBound);

            boss.AddWayPoints(new Vector2(300, -300));
            boss.AddWayPoints(new Vector2(300, 50));
            setUpWaypoints();
            this.secondPlayer = secondPlayer;
        }

        public void SpawnEnemy(int pathNumber)
        {
            Enemy enemy = new Enemy(texture, initialFrame, pathWayPoints[pathNumber][0], frameCount);
            for (int i = 0; i < pathWayPoints[pathNumber].Count; i++)
            {
                enemy.AddWayPoints(pathWayPoints[pathNumber][i]);
            }
            enemies.Add(enemy);
        }

        public void SpawnWave(int waveNumber)
        {
            waveSpawns[waveNumber] += rand.Next(MinShip, MaxShip + 1);
            totalEnemyWay ++;
            
        }

        public void updateWaveSpawns(GameTime gameTime)
        {
            spawnEnemyTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (spawnEnemyTime >= spawnEnemyDelayTime)
            {
                for (int i = pathWayPoints.Count - 2; i >= 0; i--)
                {
                    if (waveSpawns[i] > 0)
                    {
                        waveSpawns[i]--;
                        SpawnEnemy(i);
                    }
                }

                spawnEnemyTime = 0.0f;
            }

            nextWaveTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (nextWaveTime >= nextWaveDelayTime)
            {
                SpawnWave(rand.Next(0, pathWayPoints.Count-1));
                nextWaveTime = 0.0f;
            }
        }

        public void SpawnBoss()
        {
            if (bossMove > bossMoveDelay)
            {
                for (int i = 0; i < pathWayPoints[4].Count; i++)
                {
                    boss.AddWayPoints(pathWayPoints[4][i]);
                }
            }                               
        }

        public void PrepareShot(int enemyTypes, int index)
        {

            switch (enemyTypes)
            {
                case 0:
                    if (BossShowTime && !boss.Destroyed)
                    {
                        Vector2 shotBegin = boss.sprite.Location + boss.gunOffset;
                        Vector2 shotDerection = playerManager.playerSprite.Center - shotBegin;
                        shotDerection.Normalize();
                        Vector2 shotDerection1 = boss.RotateVector2(shotDerection, MathHelper.ToRadians(30));
                        shotDerection1.Normalize();
                        Vector2 shotDerection2 = boss.RotateVector2(shotDerection, MathHelper.ToRadians(-30));
                        shotDerection2.Normalize();
                        if (!playerManager.Destroyed)
                        {
                            enemyShotManager.FireShot(shotBegin, shotDerection, false);
                            enemyShotManager.FireShot(shotBegin, shotDerection1, false);
                            enemyShotManager.FireShot(shotBegin, shotDerection2, false);
                        }

                      
                        
                        if (GameSettings._2players)
                        {
                            Vector2 shot2Derection = secondPlayer.playerSprite.Center - shotBegin;
                            shot2Derection.Normalize();
                           
                            shotDerection1 = boss.RotateVector2(shot2Derection, MathHelper.ToRadians(30));
                            shotDerection1.Normalize();
                            shotDerection2 = boss.RotateVector2(shot2Derection, MathHelper.ToRadians(-30));
                            if (!secondPlayer.Destroyed)
                            {
                                enemyShotManager.FireShot(shotBegin, shot2Derection, false);
                                enemyShotManager.FireShot(shotBegin, shotDerection1, false);
                                enemyShotManager.FireShot(shotBegin, shotDerection2, false);
                            }

                           
                            
                        }   
                    }
                   
                            
                    break;
                case 1:
                    Vector2 shotBegin1 = enemies[index].sprite.Location + enemies[index].gunOffset;
                    Vector2 shotDerection3 = playerManager.playerSprite.Center - shotBegin1;

                    shotDerection3.Normalize();
                    if (!playerManager.Destroyed)
                    enemyShotManager.FireShot(shotBegin1, shotDerection3, false);
                    if (GameSettings._2players)
                    {
                        
                        Vector2 shotDerection32 = secondPlayer.playerSprite.Center - shotBegin1;
                        shotDerection32.Normalize();
                        if (!secondPlayer.Destroyed)
                        enemyShotManager.FireShot(shotBegin1, shotDerection32, false);
                    }
                    break;
            }
        }

        public void Update(GameTime gameTime)
        {
          
           
            enemyShotManager.Update(gameTime);

            if (BossShowTime && enemies.Count == 0)
            {
                boss.Update(gameTime);
                bossMove += (float)gameTime.ElapsedGameTime.TotalSeconds;
                bossShotTime +=(float)gameTime.ElapsedGameTime.TotalSeconds;
                
                if (bossShotTime >= bossShotTimeDelay)
                {
                    PrepareShot(0, 0);
                    bossShotTime = 0.0f;
                }
                else if ((float)rand.Next(0, 1000) / 10 <= shipShotChance)
                {
                    PrepareShot(0, 0);
                }

                if (Active)
                {
                    SpawnBoss();
                }
            }
            else
            {                
                if (GameSettings._hard) shipShotChance = 1f;
                else shipShotChance = 0.5f;
                for (int i = enemies.Count - 1; i >= 0; i--)
                {
                   
                    enemies[i].Update(gameTime);
                    if (!enemies[i].IsActive())
                    {
                        enemies.RemoveAt(i);
                    }
                    else
                    {
                        if ((float)rand.Next(0, 1000) / 10 <= shipShotChance)
                        {
                            PrepareShot(1, i);
                        }
                    }
                }

                if (Active)
                {
                    updateWaveSpawns(gameTime);
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            enemyShotManager.Draw(spriteBatch);
            if (BossShowTime && enemies.Count == 0)
            {
                boss.Draw(spriteBatch);
            }
            else
            {
                foreach (Enemy enemy in enemies)
                {
                    enemy.Draw(spriteBatch);
                }
            }
        }
        public void reset()
        {
            enemies.Clear();
            BossShowTime = false;
            enemyShotManager.Shots.Clear();
            boss.health = 100;
            totalEnemyWay = 0;
            boss.Destroyed = false;
            totalEnemyWay = 0;
        }

    }
}
